public class Whatsapp {
	UserListNode UsersHead = null;
	UserListNode UsersTail = null;
	Group GroupsHead = null;
	Group GroupsTail = null;

	public void AddUser(String inUserName) {

		if (UsersHead != null) {
			UserListNode ListPlaceHolder = new UserListNode();
			ListPlaceHolder.CurrUser = new User();
			ListPlaceHolder.CurrUser.Name = inUserName;
			UsersTail.Next = ListPlaceHolder;
			UsersTail = UsersTail.Next;
		} else {
			UsersHead = new UserListNode();
			UsersHead.CurrUser = new User();
			UsersHead.CurrUser.Name = inUserName;
			UsersTail = UsersHead;
		}

	}

	private User searchUser(String usserName) {
		if (UsersHead.CurrUser.Name.toString().equals(usserName)) {
			return UsersHead.CurrUser;
		}
		UserListNode userListPlaceholder = UsersHead.Next;
		while (userListPlaceholder != null) {
			if (userListPlaceholder.CurrUser.Name.toString().equals(usserName)) {
				return userListPlaceholder.CurrUser;
			}
			userListPlaceholder = userListPlaceholder.Next;
		}
		throw new RuntimeException("no such user exists");
	}

	public void CreateGroup(String inInitiator, String inGroupName) {
		Group group = new Group();
		group.GroupName = inGroupName;
		User invitor = this.searchUser(inInitiator);
		group.addGroupHead(invitor);
		if (this.GroupsHead == null) {
			this.GroupsHead = group;
			this.GroupsTail = GroupsHead;
		} else {
			this.GroupsTail.Next = group;
			GroupsTail = GroupsTail.Next;
		}

		Conversation newConversation = new Conversation();
		newConversation.ConversationGroupName = inGroupName;
		invitor.CreateConversation(newConversation);
	}

	private Group searchGroup(String groupName) {
		if (GroupsHead.GroupName.toString().equals(groupName)) {
			return GroupsHead;
		}
		Group groupHeadPlaceholder = GroupsHead.Next;
		while (groupHeadPlaceholder != null) {
			if (groupHeadPlaceholder.GroupName.toString().equals(groupName)) {
				return groupHeadPlaceholder;
			}
			groupHeadPlaceholder = groupHeadPlaceholder.Next;
		}
		throw new RuntimeException("no such group exists");
	}

	public void AddMemberToGroup(String invitorUser, String invitedUser,
			String inWelcmeText, String inGroupName) {

		Group group = this.searchGroup(inGroupName);
		group.addUser(this.searchUser(invitedUser));
		Conversation newConversation = new Conversation();
		newConversation.ConversationGroupName = inGroupName;
		this.searchUser(invitedUser).CreateConversation(newConversation);
		this.SendMessage(invitorUser, inWelcmeText, inGroupName);

	}

	public void SendMessage(String inSender, String inText, String inGroupName) {
		searchGroup(inGroupName).sendMessage(inSender, inText);
	}

	public void RemoveUserFromGroup(String inUserName, String inGroupName) {
		Group groupPointer = this.searchGroup(inGroupName);
		groupPointer.removeUserFromGroup(inUserName);
		if (groupPointer.isEmptyGroup()) {

			if (GroupsHead.GroupName.equals(inGroupName)) {
				GroupsHead = GroupsHead.Next;
				return;
			}
			Group groupPointerForBeforeGroupToDelete = GroupsHead;
			while (groupPointerForBeforeGroupToDelete.Next != null
					&& !groupPointerForBeforeGroupToDelete.Next.GroupName
							.equals(inGroupName)) {
				groupPointerForBeforeGroupToDelete = groupPointerForBeforeGroupToDelete.Next;
			}
			groupPointerForBeforeGroupToDelete.Next = groupPointerForBeforeGroupToDelete.Next.Next;
		}
	}

	public Message[] SearchMessageByText(String inUserName, String inText,
			String inGroupName) {
		Conversation tempConv = new Conversation();
		tempConv.ConversationGroupName = "forSearch";
		Message[] retVal = null;
		UserListNode usersPointer = UsersHead;
		boolean finished = false;
		while (usersPointer != null && !finished) {
			if (usersPointer.CurrUser.Name.equals(inUserName)) {
				finished = true;
				Conversation CurrentUserConv = usersPointer.CurrUser
						.GetConversation_ByGroupName(inGroupName);
				Message messagesWithFoundText = CurrentUserConv
						.searchForTextInMessages(inText);
				Message messagesWithFoundTextPointer = messagesWithFoundText;
				int i = 0;
				while (messagesWithFoundTextPointer != null) {
					i++;
					messagesWithFoundTextPointer = messagesWithFoundTextPointer.Next;
				}
				retVal = new Message[i];
				for (int j = 0; j < i; j++) {
					retVal[j] = messagesWithFoundText;
					messagesWithFoundText = messagesWithFoundText.Next;
				}

			}
			return retVal;

		}

		return null;
	}

	public String GetSearchMessageByTextString(String inUserName,
			String inText, String inGroupName) {
		Message[] msgs = SearchMessageByText(inUserName, inText, inGroupName);
		String retVal = "";
		for (int i = 0; i < msgs.length; i++) {
			retVal += msgs[i].toString() + "\n";
		}

		return retVal;
	}

	public String GetUsersList() {
		String retVal = "";
		UserListNode temp = UsersHead;
		while (temp != null) {
			retVal += temp.CurrUser.Name + "\n";
			temp = temp.Next;
		}

		return retVal;
	}

	public String GetGroupsList() {
		String retVal = "";
		Group temp = GroupsHead;
		while (temp != null) {
			retVal += temp.GroupName + "\n";
			temp = temp.Next;
		}
		return retVal;
	}

	public String GetConversationByUserAndGroup(String inUserName,
			String inGroupName) {
		UserListNode temp = UsersHead;
		while (temp != null) {
			if (temp.CurrUser.Name.equals(inUserName)) {
				return temp.CurrUser.GetConversationByGroupName(inGroupName);
			}
			temp = temp.Next;
		}

		return null;
	}

	public String GetGroupDetails(String inGroupName) {
		Group groupHeadPlaceholder = GroupsHead;
		while (groupHeadPlaceholder != null) {
			if (groupHeadPlaceholder.GroupName.equals(inGroupName)) {
				return groupHeadPlaceholder.toString();
			}

			groupHeadPlaceholder = groupHeadPlaceholder.Next;
		}

		return null;
	}

	public String GetUserConversationList(String inUserName) {
		UserListNode userListPlaceholder = UsersHead;
		while (userListPlaceholder != null) {
			if (userListPlaceholder.CurrUser.Name.equals(inUserName)) {
				return userListPlaceholder.CurrUser.GetConversationList();

			}
			userListPlaceholder = userListPlaceholder.Next;
		}

		return null;
	}

}
